<?php

namespace ai\app\libs;

use yii;

class Orm
{
    /**
     * @var Permissions
     */
    public $phpdoc;

    function __construct()
    {
        $this->phpdoc = new ReflectionDoc();
    }

    function deldir($dir)
    {
        //删除目录下的文件：
        $dh = opendir($dir);

        while ($file = readdir($dh)) {
            if ($file != "." && $file != "..") {
                $fullpath = $dir . "/" . $file;
                //chmod($dir . "/" . $file,777);
                if (!is_dir($fullpath)) {
                    unlink($fullpath);
                } else {
                    $this->deldir($fullpath);
                }
            }
        }
    }

    public function DBtoPHP()
    {

        $this->deldir(__DIR__ . "/../../db/table");
        $this->deldir(__DIR__ . "/../../db/query");
        //exit;

        OrmDBtoPHP::cteateTablesClass();
        OrmDBtoPHP::createQuerysClass();
    }
}

class OrmDBtoPHP
{
    static function cteateTablesClass()
    {
        $db = Yii::$app->db;

        $tables = $db->createCommand("show tables")->queryAll();

        $streams = '<?php
namespace ai\db\table;

require_once(__DIR__."/../base.php");
use ai\db\TablesBase;
class Tables
{
';

        foreach ($tables as $tb) {
            foreach ($tb as $t) {
                $streams .= "
    /**
    * @var TablesBase
    */
    public $" . $t . ";";

            }
        }

        $streams .= "

    function __construct()
    {
        ";
        foreach ($tables as $tb) {
            foreach ($tb as $t) {
                $streams .= "$" . 'this->' . $t . ' = new TablesBase("' . $t . '");
        ';
            }
        }
        $streams .= "
     }
}";
        //echo __DIR__."/abc.php";exit;
        //echo $streams;exit;
        $myfile = fopen(__DIR__ . "/../../db/table/tables.php", "w") or die("Unable to open file!");
        fwrite($myfile, $streams);
        fclose($myfile);
    }

    static function createQuerysClass()
    {
        $db = Yii::$app->db;
        $module = $db->createCommand("select * from sql_module")->queryAll();


        //echo json_encode($module);


        foreach ($module as $k => $m) {
            $query = $db->createCommand("select * from sql_module_items where module_id={$m['id']}")->queryAll();
            self::createQuerysBase($m['name'], $query);
        }

        self::createQuerys($module);
    }

    static function createQuerys($module)
    {
        $str = '<?php

namespace ai\db\query;
require_once(__DIR__ . "/../../base.php");
';
        foreach ($module as $k => $m) {
            $str .= '
require_once(__DIR__ . "/base/' . $m['name'] . '.php");';
        }
        $str .= '

class Querys
{
        ';
        $str .= '
    /**
    * @var \ai\db\TablesBaseQuery
    */    
    public function sql($sql){
        $cmd = new \yii\db\Query();
        $cmd = $cmd->from(["({$sql}) as a"]);

        return new \ai\db\TablesBaseQuery($cmd); 
    }
    ';

        foreach ($module as $k => $m) {
            $str .= '
    /**
    * @var base\\' . $m['name'] . '
    */
    public $' . $m['name'] . ';
    ';
        }

        $str .= '
    function __construct()
    {';


        foreach ($module as $k => $m) {
            $str .= '
        $this->' . $m['name'] . ' = new base\\' . $m['name'] . '();';
        }

        $str .= '
    }
}';
        //echo $str;exit;
        $myfile = fopen(__DIR__ . "/../../db/query/querys.php", "w+") or die("Unable to open file!");
        fwrite($myfile, $str);
        fclose($myfile);
    }

    static function createQuerysBase($modeuleName, $query)
    {
        $str = '<?php

namespace ai\db\query\base;

require_once(__DIR__ . "/../../base.php");
use ai\db\QuerysBase;

class ' . $modeuleName;
        $str .= '
{';
        foreach ($query as $q) {

            $paramsTip = '';
            $params = '';
            $paramArr = json_decode($q['sql_params'], true);
            if (count($paramArr) > 0) {
                foreach ($paramArr as $p) {
                    if (!isset($p['default'])) {
                        $params .= $p['param'] . ' , ';
                        $paramsTip .= '
     * ' . $p['param'] . ' ' . $p['name'];
                    }
                }

                foreach ($paramArr as $p) {
                    if (isset($p['default'])) {
                        //integer
                        //boolean

                        if (gettype($p['default']) == 'string') {
                            if ($p['default'] == 'array()')
                                $params .= $p['param'] . ' = array() , ';
                            else
                                $params .= $p['param'] . ' = "' . $p['default'] . '" , ';
                        }
                        if (gettype($p['default']) == 'integer') {
                            $params .= $p['param'] . ' = ' . $p['default'] . ' , ';
                        }
                        if (gettype($p['default']) == 'boolean') {
                            $params .= $p['param'] . ' = ' . ($p['default'] ? 'true' : 'false') . ' , ';
                        }
                        $paramsTip .= '
     * ' . $p['param'] . ' ' . $p['name'];
                    }
                }
            }
            $params = rtrim($params, ' ,');

//echo $paramsTip;exit;
            $str .= '

    /**
     * ' . $q['remark'] . '
     * @ver ' . $q['ver'] . '
     * @create ' . $q['addtime'] . '
     * @update ' . $q['updatetime'] . '
     * ==================================' . $paramsTip . '
     * ==================================
     * @return \ai\db\TablesBaseQuery
     */
    public function ' . $q['sql_key'] . '(' . $params . ')
    {';
            $str .= '
        $sql = "' . $q['sql_content'] . '";';
            $str .= '
        $a= new QuerysBase();';
            $str .= '
        return $a->init($sql);';
            $str .= '
    }';

        }

        $str .= '
}';
        $myfile = fopen(__DIR__ . "/../../db/query/base/{$modeuleName}.php", "w+") or die("Unable to open file!");
        fwrite($myfile, $str);
        fclose($myfile);
    }
}

use ReflectionClass;
use ReflectionMethod;

class ReflectionDoc
{
    private $sys = array();

    private function _init()
    {
        $sysAlias = Yii::$app->params['appConfig'];
        foreach ($sysAlias as $k => $item) {
            $item['path'] = "";
            if (!empty($item['namespace']))
                $item['path'] = Yii::$aliases['@' . $item['namespace']];
            $this->sys[] = $item;
        }
    }

    public function all()
    {
        $this->_init();
        $files = array();
        foreach ($this->sys as $sys) {
            $sys['items'] = $this->getFiles($sys['path'] . '\interfaces', $sys['namespace']);
            $files[] = $sys;
        }
        return $files;
    }

    public function one($appAlias)
    {
        $this->_init();
        $files = array();
        foreach ($this->sys as $sys) {
            if ($sys["alias"] == $appAlias) {
                $files = $this->getFiles($sys['path'] . '\interfaces', $sys['namespace']);
            }
        }
        return $files;
    }

    public function cur()
    {
        list($sys, $dir, $file) = explode('\\', Yii::$app->controller->className());
        $this->app_name = $sys;
        $namespace = $sys . '\\interfaces\\' . str_replace('controller', 'interface', strtolower($file));
        $action = strtolower(Yii::$app->controller->action->actionMethod);

        $methods = $this->getClassMethods($namespace);

        $curMethod = false;
        foreach ($methods as $m) {
            if ($m['alias'] == $action)
                $curMethod = $m;
        }
        if (!$curMethod) {
            echo "未找到文档注释 ai->app->libs->orm";
            exit;
        }
        return new AnalysisDoc($sys, $curMethod);
    }

    private function getFiles($basedir, $sys)
    {
        $files = array();
        if (is_dir($basedir)) {
            if ($dh = opendir($basedir)) {
                while (($file = readdir($dh)) !== false) {
                    if ($file != '.' && $file != '..') {
                        if (!is_dir($basedir . "/" . $file)) {
                            $file = strtolower($file);
                            $fileName = rtrim($file, '.php');
                            $filePaht = $basedir . '\\' . $file;
                            $namespace = $sys . '\\interfaces\\' . $fileName;
                            $classDoc = $this->getClassDoc($namespace);

                            $f = array();
                            $f['controller'] = str_replace('interface', '', $fileName);
                            $f['namespace'] = strtolower($sys . '\\controllers\\' . str_replace('interface', 'controller', $fileName));//dealers\controllers\MainController
                            //$f['path'] = $filePaht;
                            $f['alias'] = $fileName;
                            $f['md5'] = md5_file($filePaht);
                            //$f['doc'] = $classDoc;
                            $f['name'] = $this->getStrByReg($classDoc, 'name');
                            $f['sort'] = $this->getStrByReg($classDoc, 'sort',0);
                            $f['remark'] = $this->getStrByReg($classDoc, 'remark');
                            $f['deprecated'] = $this->getStrBoolByReg($classDoc, 'deprecated');
                            $f['methods'] = $this->getClassMethods($namespace);
                            $files[] = $f;
                        }
                    }
                }
                closedir($dh);
            }
        }
        return $files;
    }

    private function getClassDoc($namespace)
    {
        $reflection = new ReflectionClass ($namespace);
        $doc = $reflection->getDocComment();
        return $doc;
    }

    private function getClassMethods($namespace)
    {
        $methodsArr = array();

        $reflection = new ReflectionClass ($namespace);
        $methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC);
        foreach ($methods as $method) {
            $doc = $method->getDocComment();

            $mArr = array();
            $mArr['name'] = $this->getStrByReg($doc, "name");
            $mArr['alias'] = strtolower($method->name);
            $mArr['action'] = str_replace('action', '', strtolower($method->name));
            //$mArr['doc'] = $doc;
            $mArr['remark'] = $this->getStrByReg($doc, "remark");//描述

            $pageType = $this->getStrByReg($doc, 'type');//页面类型
            $mArr['type'] = empty($pageType) ? "page" : $pageType;
            $mArr['guest'] = $this->getStrBoolByReg($doc, 'guest');//是否不登录也可以访问 游客访问

            $mArr['sort'] = $this->getStrByReg($doc, 'sort',0);

            $mArr['deprecated'] = $this->getStrBoolByReg($doc, 'deprecated');//是否弃用

            $common = $this->getStrBoolByReg($doc, 'common');//是否通用，不需要权限验证
            $strCommon = $this->getStrByReg($doc, 'common');
            $common = !$common ? 'no' : (empty($strCommon) ? 'all' : $strCommon);
            $mArr['common'] = $common;

            $mArr['get'] = $this->getStrsByReg($doc, 'get');
            $mArr['post'] = $this->getStrsByReg($doc, 'post');
            $mArr['getall']=$this->getStrBoolByReg($doc, 'getall');
            $mArr['postall']=$this->getStrBoolByReg($doc, 'postall');
            if ($common == 'get' && count($mArr['post']) > 1)
                $mArr['postall'] = true;
            if ($common == 'post' && count($mArr['get']) > 1)
                $mArr['getall'] = true;
            if ($common == "no") {
                if (count($mArr['post']) > 1)
                    $mArr['postall'] = true;
                if (count($mArr['get']) > 1)
                    $mArr['getall'] = true;
            }


            $methodsArr[] = $mArr;
        }
        return $methodsArr;
    }


    private function getStrByReg($doc, $reg,$str='')
    {
        preg_match("/\@{$reg} .+/", $doc, $strArr);
        if (count($strArr) > 0) {
            $str = ltrim($strArr[0], "\@{$reg} ");
        }
        return $str;
    }

    private function getStrsByReg($doc, $reg)
    {
        $pArr = array();
        preg_match_all("/\@{$reg} .+/", $doc, $strArr);
        if (count($strArr) > 0) {
            foreach ($strArr[0] as $item) {
                $str = ltrim($item, "\@{$reg}");
                $str = trim($str);

                $pm = array('title' => '', "key" => "", "value" => "");
                $arr = explode(',', $str);
                foreach ($arr as $n) {
                    list($k, $v) = explode(':', $n);
                    if ($k == 't')
                        $pm['title'] = $v;
                    if ($k == 'k')
                        $pm['key'] = $v;
                    if ($k == 'v')
                        $pm['value'] = $v;
                }
                $pArr[] = $pm;
            }
        }
        return $pArr;
    }

    private function getStrBoolByReg($doc, $reg)
    {
        $bool = false;
        preg_match("/\@{$reg}/", $doc, $strArr);
        if (count($strArr) > 0) {
            $bool = true;
        }
        return $bool;
    }

}

class AnalysisDoc
{
    public $appname = '';
    public $guest = false;
    public $common = "no";

    function __construct($appName, $docArr)
    {
        $this->appname = $appName;
        $this->guest = $docArr['guest'];
        $this->common = strtolower($docArr['common']);
    }

    public function baseAuth($loginUrl)
    {

        if ($this->guest)
            return true;

        if (\Ai::$app->web->user->isGuest()) {
            Yii::$app->response->redirect($loginUrl)->send();
            exit;
        }

        if ($this->common == 'get' && Yii::$app->request->method == 'GET')
            return true;

        if ($this->common == 'get' && Yii::$app->request->method == 'POST')
            return true;

        if ($this->common == "all")
            return true;

        $user = \Ai::$app->web->user->getIdentity();
        $isSuperManager = isset($user['is_sys_manager']) ? $user['is_sys_manager'] : '0';
        if ($isSuperManager == '1')
            return true;
        $route = strtolower(Yii::$app->controller->route);
        $roleID = isset($user['role_id']) ? $user['role_id'] : 0;


        $curAllPermissions = \Ai::$db->query->sys_auth->getCurPermissions($route, $roleID)->all();

        if (Yii::$app->request->method == "GET") {

            $flag = false;
            $routeKey = '';
            foreach ($curAllPermissions as $per) {
                if ($per['req_method'] == 'getall')
                    return true;
                if (!empty($per['req_key']) && $per['req_method'] == 'get') {
                    $routeKey = $per['req_key'];
                }
                if ($per['type'] === '0')
                    $flag = true;
            }

            if (!empty($routeKey)) {
                if (isset($_GET[$routeKey])) {
                    $flag = false;
                    $curKeyValue = $_GET[$routeKey];
                    foreach ($curAllPermissions as $per) {
                        if ($per['req_key'] == $routeKey && $per['req_value'] == $curKeyValue) {
                            $flag = true;
                        }
                    }
                }
            }
            return $flag;
        }

        if (Yii::$app->request->method == "POST") {

            $flag = false;
            $routeKey = '';
            foreach ($curAllPermissions as $per) {
                if ($per['req_method'] == 'postall')
                    return true;
                if (!empty($per['req_key']) && $per['req_method'] == 'post') {
                    $routeKey = $per['req_key'];
                }
                if ($per['type'] === '0')
                    $flag = true;
            }

            if (!empty($routeKey)) {
                if (isset($_GET[$routeKey])) {
                    $flag = false;
                    $curKeyValue = $_GET[$routeKey];
                    foreach ($curAllPermissions as $per) {
                        if ($per['req_key'] == $routeKey && $per['req_value'] == $curKeyValue) {
                            $flag = true;
                        }
                    }
                }
            }
            return $flag;
        }

        return false;
    }

    /**
     * 经销商验证权限
     */
    public function dealerAuth($loginUrl)
    {
        if ($this->guest) {
            return true;
        }
        if (Yii::$app->user->isGuest) {
            Yii::$app->response->redirect($loginUrl)->send();
            exit;
        }

        if ($this->common == 'get' && Yii::$app->request->method == 'GET')
            return true;

        if ($this->common == 'get' && Yii::$app->request->method == 'POST')
            return true;

        if ($this->common == "all")
            return true;

        $user  = \app_supplier\models\User::findUserInfo(Yii::$app->user->getIdentity()->account, Yii::$app->user->getIdentity()->password);


        $isSuperManager = isset($user['is_sys_manager']) ? $user['is_sys_manager'] : '0';
        if ($isSuperManager == '1')
            return true;
        $route = strtolower(Yii::$app->controller->route);
        $roleID = isset($user['role_id']) ? $user['role_id'] : 0;


        $curAllPermissions = \Ai::$db->query->sys_auth->getCurPermissions($route, $roleID)->all();



        if (Yii::$app->request->method == "GET") {

            $flag = false;
            $routeKey = '';
            foreach ($curAllPermissions as $per) {
                if ($per['req_method'] == 'getall')
                    return true;
                if (!empty($per['req_key']) && $per['req_method'] == 'get') {
                    $routeKey = $per['req_key'];
                }
                if ($per['type'] === '0')
                    $flag = true;
            }

            if (!empty($routeKey)) {
                if (isset($_GET[$routeKey])) {
                    $flag = false;
                    $curKeyValue = $_GET[$routeKey];
                    foreach ($curAllPermissions as $per) {
                        if ($per['req_key'] == $routeKey && $per['req_value'] == $curKeyValue) {
                            $flag = true;
                        }
                    }
                }
            }
            return $flag;
        }

        if (Yii::$app->request->method == "POST") {
            $flag = false;
            $routeKey = '';

            foreach ($curAllPermissions as $per) {
                if ($per['req_method'] == 'postall')
                    return true;
                if (!empty($per['req_key']) && $per['req_method'] == 'post') {
                    $routeKey = $per['req_key'];
                }
                if ($per['type'] === '0')
                    $flag = true;
            }

            if (!empty($routeKey)) {
                if (isset($_GET[$routeKey])) {
                    $flag = false;
                    $curKeyValue = $_GET[$routeKey];
                    foreach ($curAllPermissions as $per) {
                        if ($per['req_key'] == $routeKey && $per['req_value'] == $curKeyValue) {
                            $flag = true;
                        }
                    }
                }
            }

            return $flag;
        }
        return false;
    }

}


